#ifndef YUFA_H
#define YUFA_H
#include <iostream>
#include <set>
#include <fstream>
#include <cstdlib>
#include <queue>
#include <string>
#include <cstring>
#include <sstream>
#include <map>
#include <stack>
#include <vector>

using namespace std;

char WenFaPath[] = "wenfa.txt"; //????
char TokenPath[] = "token.txt"; // TOKEN????
ifstream ReadFile;
set<string> Zhongjie;
set<string> false_Zhongjie;
string wenfa[200][2];
vector<vector<string>> table;
queue<string> Token;
// 1.??????
//???????????
bool In_Zhongjie(string x)
{
    int status = 0;
    for (string t : Zhongjie)
    {
        if (t.length() != x.length())
            continue;
        // cout<<"x = "<<x<<endl;
        // cout<<"t = "<<t<<endl;
        status = 1;

        for (int i = 0; i < t.length(); i++)
        {
            if (x[i] != t[i])
                status = 0;
        }
        if (status)
            break;
    }
    switch (status)
    {
    case 1:
        return true;
        break;

    default:
        return false;
        break;
    }
}
//????????????
bool In_Feizhong(string str)
{
    int status = 0;
    for (string s : false_Zhongjie)
    {
        if (s.length() != str.length())
            continue;
        status = 1;
        for (int i = 0; i < s.length(); i++)
        {
            if (s[i] != str[i])
                status = 0;
        }
        if (status)
            break;
    }
    switch (status)
    {
    case 1:
        return true;
        break;

    default:
        return false;
        break;
    }
}

//?????????
void Deal_Wenfa()
{
    string str;
    int i = 0;
    cin.unsetf(ios::skipws);
    ReadFile.open(WenFaPath, ios::in);

    while (!ReadFile.eof())
    { //??????????????
        getline(ReadFile, str);
        // cout<<"WENFA = "<<str<<endl;
        int status = 1;
        for (int j = 0; j < str.length(); j = j + 1)
        {
            if (str[j] == '-' && str[j + 1] == '>')
            {
                status = 0;
                j += 3;
            }
            switch (status)
            {
            case 1:
                if (str[j] != ' ')
                    wenfa[i][0] = wenfa[i][0] + str[j];
                // cout<<"wenfa["<<i<<"][0] = "<<wenfa[i][0]<<endl;
                break;

            default:
                if (wenfa[i][1].length() >= 5)
                {
                    if (wenfa[i][1].substr(wenfa[i][1].length() - 5).compare("ORDER") == 0)
                    {
                        wenfa[i][1] = wenfa[i][1] + str[++j];
                    }
                    else if (wenfa[i][1].substr(wenfa[i][1].length() - 5).compare("GROUP") == 0)
                    {
                        wenfa[i][1] = wenfa[i][1] + str[++j];
                    }
                    else
                        wenfa[i][1] = wenfa[i][1] + str[j];
                }
                else
                    wenfa[i][1] = wenfa[i][1] + str[j];
                // cout << "wenfa[" << i << "][1] = " << wenfa[i][1] << endl;
                break;
            }
        }
        status = 1;
        i++;
    }

    for (int j = 0; j < 200; j = j + 1)
    { // ?????
        if (wenfa[j][0] != " ")
            false_Zhongjie.insert(wenfa[j][0]);
    }

    for (int j = 0; j < 200; j = j + 1)
    { //????????
        istringstream str(wenfa[j][1]);
        string out;
        while (str.good())
        { 
            getline(str, out, ' ');
            if (!out.empty() && (!In_Feizhong(out)))
            {

                Zhongjie.insert(out);

                // cout << "out = " << Zhongjie.end() << endl;
            }
        }
    }
    return;
}

//??token??
ifstream token;
void read_token()
{
    string str;
    string shuxing;
    string cisu;
    int i = 0;
    cin.unsetf(ios::skipws);
    token.open("token.txt", ios::in);
    if (token.is_open())
        cout << "open token  success" << endl;
    else
    {
        cout << "open token error" << endl;
        return;
    }
    // Token.push("#");
    while (!token.eof())
    {
        getline(token, str);
        if (str.empty())
        {
            cout << "read error" << endl;
            break;
        }
        int flag = 1;
        for (int j = 0; j < str.length(); j++)
        {
            if (str[j] == ' ')
            {
                if (str[j + 1] == '<')
                {
                    cisu = str.substr(0, j);
                    int len = str.length();
                    shuxing = str.substr(j + 2, len - j);
                }
            }
        }
        for (int j = 0; j < shuxing.length(); j++)
        {
            if (shuxing[j] == ',')
            {
                shuxing = shuxing.substr(0, j);
                break;
            }
        }
        i++;

        if (shuxing.compare("KW") == 0)
        {
            if (cisu.compare("ORDER BY") == 0)
            {
                Token.push("ORDERBY");
            }
            else if (cisu.compare("GROUP BY") == 0)
            {
                Token.push("GROUPBY");
            }
            else
                Token.push(cisu);
        }
        else if (shuxing.compare("OP") == 0)
        {
            Token.push(cisu);
        }
        else if (shuxing.compare("SE") == 0)
        {
            Token.push(cisu);
        }
        else if (shuxing.compare("IDN") == 0)
        {
            Token.push("IDN");
        }
        else if (shuxing.compare("INT") == 0)
        {
            Token.push("INT");
        }
        else if (shuxing.compare("FLOAT") == 0)
        {
            Token.push("FLOAT");
        }
        else if (shuxing.compare("STRING") == 0)
        {
            Token.push("STRING");
        }
        else
        {
            Token.push(cisu);
        }
        cout << Token.back() << endl;
    }
    return;
}

// 2.??????
//set??
set<string> set_connent(set<string> x, set<string> y, int status)
{
    if (status)
        y.erase("$");
    set<string>::iterator i;
    for (i = y.begin(); i != y.end(); i++)
        x.insert(*i);
    return x;
}

//??string???set?
bool set_in(string str, set<string> y)
{
    int status = 0;
    if (y.empty())
        return false;
    set<string>::iterator i;
    for (string j : y)
    {
        if (j.compare(str) == 0)
            status = 1;
    }
    switch (status)
    {
    case 1:
        return true;
        break;

    default:
        return false;
        break;
    }
}
// 3.set??
bool set_commpare(set<string> x, set<string> y, bool flag)
{
    if (flag)
        y.erase("$");
    int status = 1;
    bool res = true;
    set<string>::iterator i;
    for (string j : y)
    {
        if (!set_in(j, x))
            res = false;
    }
    return res;
}

// 4.??set?????
set<string> set_get(string str)
{
    set<string> x;
    for (int i = 0; i < 200; i++)
    {
        if (wenfa[i][0].compare(str) == 0)
        {
            x.insert(wenfa[i][1]);
        }
    }
    return x;
}
// 5.????????
string get_table(string x, string y)
{
    string str;
   // cout<<"stacktopx"<<x<<endl;
    //cout<<"temptokeny"<<y<<endl;
    if(x == "expressions"&&y=="IDN")
    {str = "expressions -> expression expressionRec";
    return str;
    }
    vector<vector<string>> contemp_table = table;
    vector<string> row = contemp_table.front();
    int j = 0;
    for (int i = 1; i < row.size(); i++)
    {
        if (y.compare(row.at(i)) == 0)
        {
            j = i;
        }
    }
    for (int i = 1; i < contemp_table.size(); i++)
    {
        vector<string> contemp_row = contemp_table.at(i);
        if (x.compare(contemp_row.at(0)) == 0)
        {
            str = contemp_row.at(j);
            if (str.length() < 1)
                str = get_table(x, "$");
        }
    }
    return str;
}
// 6.??????
string stack_print(stack<string> str)
{
    string res;
    while (!str.empty())
    {
        string temp = str.top();
        res += temp;
        str.pop();
    }
    return res;
}

//??????
// 1.first
map<string, set<string>> FIRST;
ofstream First;
void first_write()
{
    First << "First???" << endl;
    for (string x : false_Zhongjie)
    {
        if (x == "")
            continue;
        set<string> temp = FIRST[x];
       // if(x == "GROUPBY")
        //x = "GROUP BY";
        First << x << ":";
        for (string y : temp)
        {
            First << y << "  ";
        }
        First << endl;
    }
    for (string x : Zhongjie)
    {
        set<string> temp = FIRST[x];
        First << x << ":";
        for (string y : temp)
            First << y << "  ";
        First << endl;
    }
}
// 2.follow
map<string, set<string>> FOLLOW;
ofstream Follow;
void write_fellow()
{
    Follow << "Fellow???" << endl;
    for (string x : false_Zhongjie)
    {
        if (x == "")
            continue;
        set<string> temp = FOLLOW[x];
        Follow << x << ": ";
        for (string y : temp)
        {
            Follow << y << ": ";
        }
        Follow << endl;
    }
}

// 3.table
int get_len(string str)
{
    return str.length();
}
ofstream Writer;
void write_table()
{
    Writer.open("table.txt", ios::out);
    for (vector<string> x : table)
    {
        for (int i = 0; i < x.size(); i++)
        {
            if (x[i] == "")
            {
                break;
            }
        }
        for (string y : x)
        {
            int len = get_len(y);
            if (len > 0)
            {
                Writer << "\"" + y + "\""
                       << ",";
            }
            else
            {
                Writer << "\""
                       << "#"
                       << " \""
                       << ",";
            }
        }
        Writer << endl;
    }
    Writer.close();
    remove("table.csv");
    rename("table.txt", "table.csv");
    return;
}

#endif